<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Dialogs</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="winapi, Windows API, C, no MFC, Dialogs">
<meta name="description" content="In this part of the Winapi tutorial we work
with dialogs.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Dialogs</h1>


<p>
Dialog windows or dialogs are an indispensable part of most modern GUI 
applications. A dialog is defined as a conversation between two or more persons. 
In a computer application a dialog is a window which is used to "talk" to 
the application. A dialog is used to input data, modify data, change the application settings etc. 
Dialogs are important means of communication between a user and a computer program.
</p>

<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* LargeSquare */
google_ad_slot = "5070696322";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>


<h2>Modeless Dialog</h2>

<p>
Modeless dialogs does not restrict you to working with a particular window. 
A user can switch between a dialog box and other windows of a program.
A typical modeless dialog is a Find/Replace dialog or a floating toolbar.
</p>

<pre class="code">
#include &lt;windows.h&gt;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

void CreateDialogBox(HWND);
void RegisterDialogClass(HWND);

HINSTANCE ghInstance;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow )
{
  MSG  msg ;    
  HWND hwnd;

  WNDCLASS wc = {0};
	
  wc.lpszClassName = TEXT( "Window" );
  wc.hInstance     = hInstance ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  
  RegisterClass(&amp;wc);
  hwnd = CreateWindow( wc.lpszClassName, TEXT("Window"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 250, 150, NULL, NULL, hInstance, NULL);  

  ghInstance = hInstance;

  while( GetMessage(&amp;msg, NULL, 0, 0)) {
    DispatchMessage(&amp;msg);
  }
  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
  switch(msg)  
  {
      case WM_CREATE:
          RegisterDialogClass(hwnd);
          CreateWindow(TEXT("button"), TEXT("Show dialog"),    
              WS_VISIBLE | WS_CHILD ,
              20, 50, 95, 25,        
              hwnd, (HMENU) 1, NULL, NULL);  
          break;

      case WM_COMMAND:
          CreateDialogBox(hwnd);
          break;

      case WM_DESTROY:
      {
          PostQuitMessage(0);
          return 0;
      }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

LRESULT CALLBACK DialogProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{

  switch(msg)  
  {
    case WM_CREATE:
	CreateWindow(TEXT("button"), TEXT("Ok"),    
	      WS_VISIBLE | WS_CHILD ,
	      50, 50, 80, 25,        
	      hwnd, (HMENU) 1, NULL, NULL);  
	break;

    case WM_COMMAND:
	DestroyWindow(hwnd);
	break;

    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;       

  }
  return (DefWindowProc(hwnd, msg, wParam, lParam));

}


void RegisterDialogClass(HWND hwnd) 
{
  WNDCLASSEX wc = {0};
  wc.cbSize           = sizeof(WNDCLASSEX);
  wc.lpfnWndProc      = (WNDPROC) DialogProc;
  wc.hInstance        = ghInstance;
  wc.hbrBackground    = GetSysColorBrush(COLOR_3DFACE);
  wc.lpszClassName    = TEXT("DialogClass");
  RegisterClassEx(&amp;wc);

}

void CreateDialogBox(HWND hwnd)
{
  CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_TOPMOST,  TEXT("DialogClass"), TEXT("Dialog Box"), 
        WS_VISIBLE | WS_SYSMENU | WS_CAPTION , 100, 100, 200, 150, 
        NULL, NULL, ghInstance,  NULL);
}
</pre>


<p>
A dialog is only a special kind of a window. It is created as a normal window with some specific flags.
</p>

<pre class="explanation">
  CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_TOPMOST,  TEXT("DialogClass"), TEXT("Dialog Box"), 
        WS_VISIBLE | WS_SYSMENU | WS_CAPTION , 100, 100, 200, 150, 
        NULL, NULL, ghInstance,  NULL);
</pre>

<p>
The dialog is crated with a combination of regular flags WS_VISIBLE | WS_SYSMENU | WS_CAPTION 
and extended flags WS_EX_DLGMODALFRAME | WS_EX_TOPMOST.
</p>


<br>
<img src="/img/gui/winapi/dialog.jpg" alt="Modeless dialog">
<div class="figure">Figure: Modeless dialog</div>

<h2>Common Dialog Boxes</h2>

<p>
These are dialogs for performing common tasks. Opening and saving files, printing documents, choosing color etc.
Common dialog boxes save programmers a lot of work. They  help promote standards in applications. 
</p>

<h3>Color dialog box</h3>

<p>
This is a common dialog for choosing color. 
</p>

<pre class="code">
#include &lt;windows.h&gt;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK PanelProc(HWND, UINT, WPARAM, LPARAM);

void RegisterPanel(void);
COLORREF ShowColorDialog(HWND);

COLORREF gColor = RGB(255, 255, 255);

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow )
{
  MSG  msg ;    
  WNDCLASS wc = {0};
  wc.lpszClassName = TEXT( "Color dialog box" );
  wc.hInstance     = hInstance ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  
  RegisterClass(&amp;wc);
  CreateWindow( wc.lpszClassName, TEXT("Color dialog box"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                150, 150, 250, 200, 0, 0, hInstance, 0);  

  while( GetMessage(&amp;msg, NULL, 0, 0)) {
    DispatchMessage(&amp;msg);
  }
  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{

  static HWND hwndPanel;

    
  switch(msg)  
  {
    	case WM_CREATE:
  	{
          CreateWindow(TEXT("button"), TEXT("Color"),    
	       WS_VISIBLE | WS_CHILD ,
	       20, 30, 80, 25,        
	       hwnd, (HMENU) 1, NULL, NULL);    

          RegisterPanel();
          hwndPanel = CreateWindow(TEXT("Panel"), NULL, 
		           WS_CHILD | WS_VISIBLE,
		           130, 30, 80, 80,
		           hwnd, (HMENU) 2, NULL, NULL);   
          break;
	}

	case WM_COMMAND:
	{
           gColor = ShowColorDialog(hwnd);
           InvalidateRect(hwndPanel, NULL, TRUE);    
           break;
	}

      case WM_DESTROY:
      {
          PostQuitMessage(0);
          break;
      }
  }

  return DefWindowProc(hwnd, msg, wParam, lParam);
}	

LRESULT CALLBACK PanelProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
  HDC hdc;
  PAINTSTRUCT ps; 
  RECT rect;

  switch(msg)  
  {
    case WM_PAINT:
    {
        GetClientRect(hwnd, &amp;rect);
        hdc = BeginPaint(hwnd, &amp;ps);
        SetBkColor(hdc, gColor);
        ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &amp;rect, TEXT(""), 0, NULL);
        EndPaint(hwnd, &amp;ps);
        break;
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}


COLORREF ShowColorDialog(HWND hwnd) {

  CHOOSECOLOR cc;                 
  static COLORREF crCustClr[16];     

  ZeroMemory(&amp;cc, sizeof(cc));
  cc.lStructSize = sizeof(cc);
  cc.hwndOwner = hwnd;
  cc.lpCustColors = (LPDWORD) crCustClr;
  cc.rgbResult = RGB(0, 255, 0);
  cc.Flags = CC_FULLOPEN | CC_RGBINIT;
  ChooseColor(&amp;cc);

  return cc.rgbResult;
}

void RegisterPanel(void) {

  WNDCLASS rwc = {0};
  rwc.lpszClassName = TEXT( "Panel" );
  rwc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  rwc.lpfnWndProc   = PanelProc;
  RegisterClass(&amp;rwc);
}
</pre>

<p>
In our example, we have a button control and a child window. The color of 
the child window is white at the beginning.We can change the color of the 
child window, by pressing on the button and choosing a custom color value.
</p>

<pre class="explanation">
 COLORREF gColor = RGB(255, 255, 255);
</pre>

<p>
We define a global color value. White by default.
</p>

<pre class="explanation">
 gColor = ShowColorDialog(hwnd);
</pre>

<p>
The color dialog box is shown in the <i>ShowColorDialog()</i> user function. 
The function returns the chosen color value.
</p>

<pre class="explanation">
 CHOOSECOLOR cc; 
</pre>

<p>
To create a color dialog box, we must define and fill a <i>CHOOSECOLOR</i> structure.
</p>

<pre class="explanation">
 cc.rgbResult = RGB(0, 255, 0);
 cc.Flags = CC_FULLOPEN | CC_RGBINIT;
</pre>

<p>
If we provide the <i>CC_RGBINIT</i> than the <i>rgbResult</i> member is the 
initial selected color, when the dialog is displayed. If the user clicks the 
OK button, <i>rgbResult</i> specifies the user's color selection.
</p>

<pre class="explanation">
 ChooseColor(&amp;cc);
</pre>

<p>
The color dialog box is displayed.
</p>

<pre class="explanation">
 gColor = ShowColorDialog(hwnd);
 InvalidateRect(hwndPanel, NULL, TRUE); 
</pre>

<p>
After we obtain the color value, we call the <i>InvalidateRect()</i> function. 
This function will send <i>WM_PAINT</i> message to our child window. 
</p>

<pre class="explanation">
 SetBkColor(hdc, gColor);
 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &amp;rect, TEXT(""), 0, NULL);
</pre>

<p>
In the panel procedure, we change the background color of the child window. 
Besides displaying text on the window, the <i>ExtTextOut()</i> function 
can also change the window background color. We won't display any text, we 
only change the background color. 
If we provide the <i>ETO_OPAQUE</i> flag, the <i>ExtTextOut()</i> function 
will use the color, specified by the <i>SetBkColor()</i> function.
</p>


<br>
<img src="/img/gui/winapi/colordialog.jpg" alt="Color dialog box">
<div class="figure">Figure: Color dialog box</div>


<h3>Openfile dialog box</h3>

<p>
This is a common dialog for opening files. Don't use UNICODE, to compile this example. 
</p>

<pre class="code">
#include &lt;windows.h&gt;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CreateMenubar(HWND);
void OpenDialog(HWND);
void LoadFile(LPSTR);

#define IDM_FILE_NEW 1
HWND ghwndEdit;


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow )
{
  MSG  msg ;    
  WNDCLASS wc = {0};
  wc.lpszClassName = TEXT( "Opendialog" );
  wc.hInstance     = hInstance ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);

  
  RegisterClass(&amp;wc);
  CreateWindow( wc.lpszClassName, TEXT("Opendialog"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                150, 150, 265, 200, 0, 0, hInstance, 0);  

  while( GetMessage(&amp;msg, NULL, 0, 0)) {
    DispatchMessage(&amp;msg);
  }
  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
   
  switch(msg)  
  {
      case WM_CREATE:
          ghwndEdit = CreateWindowEx(WS_EX_RIGHTSCROLLBAR, TEXT("edit"), NULL,    
                        WS_VISIBLE | WS_CHILD | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE,
                        0, 0, 260, 180,        
                        hwnd, (HMENU) 1, NULL, NULL);    


	   CreateMenubar(hwnd);
	   break;

      case WM_SIZE:
          SetWindowPos(ghwndEdit, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam),
             SWP_NOMOVE | SWP_NOZORDER);
          break;

      case WM_COMMAND:
	   if (wParam==IDM_FILE_NEW) {
              OpenDialog(hwnd);
	    }
          break;

      case WM_DESTROY:
          PostQuitMessage(0);
          break;
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}	

void CreateMenubar(HWND hwnd) {
  HMENU hMenubar;
  HMENU hMenu;

  hMenubar = CreateMenu();
  hMenu = CreateMenu();
  AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu, TEXT("&amp;File"));
  AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, TEXT("&amp;Open"));
  SetMenu(hwnd, hMenubar);
}

void OpenDialog(HWND hwnd) 
{
  OPENFILENAME ofn;
  TCHAR szFile[MAX_PATH];

 
  ZeroMemory(&amp;ofn, sizeof(ofn));
  ofn.lStructSize = sizeof(ofn);
  ofn.lpstrFile = szFile;
  ofn.lpstrFile[0] = '\0';
  ofn.hwndOwner = hwnd;
  ofn.nMaxFile = sizeof(szFile);
  ofn.lpstrFilter = TEXT("All files(*.*)\0*.*\0");
  ofn.nFilterIndex = 1;
  ofn.lpstrInitialDir = NULL;
  ofn.lpstrFileTitle = NULL;
  ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  

  if(GetOpenFileName(&amp;ofn))
      LoadFile(ofn.lpstrFile);
}

void LoadFile(LPSTR file)
{
  HANDLE hFile;
  DWORD dwSize;
  DWORD dw;

  LPBYTE lpBuffer = NULL;

  hFile = CreateFile(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  dwSize = GetFileSize(hFile, NULL);
  lpBuffer = (LPBYTE) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, dwSize + 1);
  ReadFile(hFile, (LPWSTR)lpBuffer, dwSize, &amp;dw, NULL);
  CloseHandle(hFile);
  lpBuffer[dwSize] = 0;
  SetWindowText(ghwndEdit, (LPSTR) lpBuffer);
  HeapFree(GetProcessHeap(), 0, lpBuffer);
}
</pre>

<p>
In this example, we create a window with a multiline edit control. 
</p>

<p>
To create an openfile dialog box, we create and fill the <i>OPENFILENAME</i> structure.
</p>

<pre class="explanation">
 ofn.lpstrFile = szFile;
</pre>

<p>
If the OpenFileName() function returns TRUE, the name of the selected file is in the <i>lpstrFile</i> member.
</p>

<pre class="explanation">
 ofn.lpstrFilter = TEXT("All files(*.*)\0*.*\0");
</pre>

<p>
This defines the file filter. In our example, the dialog shows all file types.
</p>

<pre class="explanation">
 ofn.nFilterIndex = 1;
</pre>

<p>
 Specifies the index of the currently selected filter in the File Types combo box control. 
</p>


<pre class="explanation">
 if(GetOpenFileName(&amp;ofn))
     LoadFile(ofn.lpstrFile);
</pre>

<p>
We call the <i>GetOpenFileName()</i> function to show the Openfile dialog box. 
If we click on the Open button, the function returns TRUE
and we call the user defined <i>LoadFile()</i> function.
</p>

<p>
Inside the <i>LoadFile()</i> function, we read the file and put the contents of 
the file into the edit control. We create a file handle. Than we 
find out the file size. Allocate dynamic memory for the contents of the file. 
Read the contents into the memory and put them into the edit control.
To put the contents into the edit control, we call the <i>SetWindowText()</i> 
function. We must not forget to close the file handle and free the 
dynamic memory.
</p>


<img src="/img/gui/winapi/opendialog.jpg" alt="Openfile dialog box">
<div class="figure">Figure: Openfile dialog box</div>


<p>
In this part of the Winapi tutorial, we worked with dialogs.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br> 


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified July 21, 2007  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
